﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;

namespace IOCDI
{
    /// <summary>
    /// 容器
    /// </summary>
    public static class Container
    {
        /// <summary>
        /// 对象容器字典
        /// </summary>
        private static Dictionary<Type, object> _objcontainer { get; } = new Dictionary<Type, object>();

        #region 注册

        /// <summary>
        /// 注册全局单例（单一类型）
        /// </summary>
        /// <typeparam name="T"></typeparam>
        public static void RegisterSingleton<T>()
        {
            RegisterSingleton(typeof(T), Activator.CreateInstance(typeof(T), GetCotrParams<T>().ToArray()));
        }

        /// <summary>
        /// 注册全局单例（支持抽象类映射实现类）
        /// </summary>
        /// <typeparam name="T1">TypeFrom</typeparam>
        /// <typeparam name="T2">TypeTo</typeparam>
        public static void RegisterSingleton<T1, T2>()
        {
            RegisterSingleton(typeof(T1), Activator.CreateInstance(typeof(T2), GetCotrParams<T2>().ToArray()));
        }

        /// <summary>
        /// 注册全局单例
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        public static void RegisterSingleton<T>(object obj)
        {
            RegisterSingleton(typeof(T), obj);
        }

        /// <summary>
        /// 容器添加（不支持构造）
        /// </summary>
        /// <param name="type"></param>
        /// <param name="obj"></param>
        public static void RegisterSingleton(Type type, object obj)
        {
            if (_objcontainer.ContainsKey(type) == false)
                _objcontainer[type] = obj;
            else
            {
                throw new ArgumentException("此类型已注册");
            }
        }

        #endregion

        #region 取出

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static T Resolve<T>()
        {
            return (T)Resolve(typeof(T));
        }


        public static object Resolve(Type type)
        {
            if (_objcontainer.ContainsKey(type) == false)
                throw new ArgumentException("使用了未注册的类型");
            return _objcontainer[type];
        }

        #endregion

        /// <summary>
        /// 获取构造参数
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        private static List<object> GetCotrParams<T>()
        {
            var type = typeof(T);
            List<object> objparam = new List<object>();
            /*
             * 原理：找到构造方法的参数表
             * 拼接构造方法的参数
             * 通过构造参数构建对象
             */
            System.Reflection.MemberInfo ctor = type.GetMembers().FirstOrDefault(s => s.Name.Contains("ctor"));
            if (ctor.ToString().Length > 12)
            {
                string[] paramarry = ctor.ToString().Split(new char[] { '(', ')' }, StringSplitOptions.RemoveEmptyEntries)[1]
                                      .Split(new char[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries);
                List<Type> paramtypes = new List<Type>();
                if (paramarry.Length > 0)
                {
                    foreach (var item in paramarry)
                    {
                        paramtypes.Add(Type.GetType(item));
                    }
                }
                paramtypes.ForEach(s =>
                {
                    if (_objcontainer.ContainsKey(s))
                        objparam.Add(_objcontainer[s]);
                    else
                        throw new ArgumentException("使用了未注入的依赖");
                });
            }
            return objparam;
        }

    }
}
